﻿using System;
using System.Collections.Generic;
namespace GameCore
{
    public delegate void Callback();
    public delegate void Callback<T>(T arg1);
    public delegate void Callback<T, U>(T arg1, U arg2);
    public delegate void Callback<T, U, V>(T arg1, U arg2, V arg3);
    public delegate void Callback<T, U, V, W>(T arg1, U arg2, V arg3, W arg4);
    public delegate void Callback<T, U, V, W, X>(T arg1, U arg2, V arg3, W arg4, X arg5);

    public delegate void Callback_NetMessage_Handle(object _data);

    /// <summary>
    /// 静态全局消息分发执行管理器
    /// </summary>
    public static class EventMgr
    {
        /// <summary>
        /// 消息列表
        /// </summary>
        private static Dictionary<string, List<Delegate>> MsgList = new Dictionary<string, List<Delegate>>();

        /// <summary>
        /// 回调执行队列
        /// </summary>
        private static Queue<Action> callbackQueue = new Queue<Action>();

        /// <summary>
        /// 锁定
        /// </summary>
        private static object lockObject = new object();

        /// <summary>
        /// 移除监听
        /// </summary>
        /// <param name="msgName"></param>
        /// <param name="callBack"></param>
        private static void _AddListener(string msgName,Delegate callBack) {
            if (MsgList.ContainsKey(msgName))
            {
                List<Delegate> dList = MsgList[msgName];

                for (int i = 0; i < dList.Count; ++i)
                {
                    if (callBack == dList[i])
                    {
                        return;
                    }
                }

                dList.Add(callBack);
            }
            else
            {
                List<Delegate> list = new List<Delegate>();
                list.Add(callBack as Delegate);
                MsgList.Add(msgName, list);
            }
        }

        /// <summary>
        /// 添加监听
        /// </summary>
        /// <param name="msgName"></param>
        /// <param name="callBack"></param>
        private static void _RemoveListener(string msgName, Delegate callBack) {
            if (MsgList.ContainsKey(msgName)) {
                MsgList[msgName].Remove(callBack);
            }
        }

        private static void Error(string msgName,Delegate callBack) {
            Logger.LogErrorFormat("事件发送参数与接收方法不匹配=>MsgName:{0},TargetName:{1},MethodName:{2}",msgName,callBack.Target, callBack.Method.Name);
        }

        /// <summary>
        /// 添加普通消息监听者
        /// </summary>
        /// <param name="msgName"></param>
        /// <param name="_callback"></param>
        public static void AddListener(string msgName, Callback _callback)
        {
            _AddListener(msgName, _callback);
        }
        public static void AddListener<T>(string msgName, Callback<T> _callback)
        {
            _AddListener(msgName, _callback);
        }
        public static void AddListener<T, U>(string msgName, Callback<T, U> _callback)
        {
            _AddListener(msgName, _callback);
        }
        public static void AddListener<T, U, V>(string msgName, Callback<T, U, V> _callback)
        {
            _AddListener(msgName, _callback);
        }

        public static void AddListener<T, U, V, W>(string msgName, Callback<T, U, V, W> _callback)
        {
            _AddListener(msgName, _callback);
        }

        public static void AddListener<T, U, V, W, X>(string msgName, Callback<T, U, V, W, X> _callback)
        {
            _AddListener(msgName, _callback);
        }


        /// <summary>
        /// 删除普通消息监听者
        /// </summary>
        /// <param name="msgName"></param>
        /// <param name="_callback"></param>
        public static void RemoveListener(string msgName, Callback _callback)
        {
            _RemoveListener(msgName, _callback);
        }
        public static void RemoveListener<T>(string msgName, Callback<T> _callback)
        {
            _RemoveListener(msgName, _callback);
        }
        public static void RemoveListener<T, U>(string msgName, Callback<T, U> _callback)
        {
            _RemoveListener(msgName, _callback);
        }
        public static void RemoveListener<T, U, V>(string msgName, Callback<T, U, V> _callback)
        {
            _RemoveListener(msgName, _callback);
        }

        public static void RemoveListener<T, U, V, W>(string msgName, Callback<T, U, V, W> _callback)
        {
            _RemoveListener(msgName, _callback);
        }

        public static void RemoveListener<T, U, V, W, X>(string msgName, Callback<T, U, V, W, X> _callback)
        {
            _RemoveListener(msgName, _callback);
        }

        /// <summary>
        /// 广播普通消息
        /// </summary>
        /// <param name="msgName"></param>
        public static void Brocast(string msgName)
        {
            if (MsgList.ContainsKey(msgName))
            {
                List<Delegate> list = MsgList[msgName];
                if (list.Count == 0)
                    return;
                Action action = () => {
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (list[i] is Callback)
                        {
                            (list[i] as Callback).Invoke();
                        }
                        else
                        {
                            Error(msgName,list[i]);
                        }
                    }
                };
                AddCallBack(action);
            }
        }
        public static void Brocast<T>(string msgName, T arg1)
        {
            if (MsgList.ContainsKey(msgName))
            {
                List<Delegate> list = MsgList[msgName];
                if (list.Count == 0)
                    return;
                Action action = () => {
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (list[i] is Callback<T>)
                        {
                            (list[i] as Callback<T>).Invoke(arg1);
                        }
                        else
                        {
                            Error(msgName, list[i]);
                        }
                    }
                };
                AddCallBack(action);
            }
        }
        public static void Brocast<T, U>(string msgName, T arg1, U arg2)
        {
            if (MsgList.ContainsKey(msgName))
            {
                List<Delegate> list = MsgList[msgName];
                if (list.Count == 0)
                    return;
                Action action = () => {
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (list[i] is Callback<T, U>)
                        {
                            (list[i] as Callback<T, U>).Invoke(arg1, arg2);
                        }
                        else
                        {
                            Error(msgName, list[i]);
                        }
                    }
                };
                AddCallBack(action);
            }
        }
        public static void Brocast<T, U, V>(string msgName, T arg1, U arg2, V arg3)
        {
            if (MsgList.ContainsKey(msgName))
            {
                List<Delegate> list = MsgList[msgName];
                if (list.Count == 0)
                    return;
                Action action = () => {
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (list[i] is Callback<T, U, V>)
                        {
                            (list[i] as Callback<T, U, V>).Invoke(arg1, arg2, arg3);
                        }
                        else
                        {
                            Error(msgName, list[i]);
                        }
                    }
                };
                AddCallBack(action);
            }
        }

        public static void Brocast<T, U, V, W>(string msgName, T arg1, U arg2, V arg3, W arg4)
        {
            if (MsgList.ContainsKey(msgName))
            {
                List<Delegate> list = MsgList[msgName];
                if (list.Count == 0)
                    return;
                Action action = () => {
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (list[i] is Callback<T, U, V, W>)
                        {
                            (list[i] as Callback<T, U, V, W>).Invoke(arg1, arg2, arg3, arg4);
                        }
                        else
                        {
                            Error(msgName, list[i]);
                        }
                    }
                };
                AddCallBack(action);
            }
        }

        public static void Brocast<T, U, V, W, X>(string msgName, T arg1, U arg2, V arg3, W arg4, X arg5)
        {
            if (MsgList.ContainsKey(msgName)) {
                List<Delegate> list = MsgList[msgName];
                if (list.Count == 0)
                    return;
                Action action = () => {
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (list[i] is Callback<T, U, V, W, X>)
                        {
                            (list[i] as Callback<T, U, V, W, X>).Invoke(arg1, arg2, arg3, arg4, arg5);
                        }
                        else
                        {
                            Error(msgName, list[i]);
                        }
                    }
                };
                AddCallBack(action);
            }
        }

        /// <summary>
        /// 添加回调到回调队列
        /// </summary>
        public static void AddCallBack(Action action)
        {
            callbackQueue.Enqueue(action);
        }


        /// <summary>
        /// 执行回调函数
        /// </summary>
        public static void ExecuteCallBack()
        {
            lock (lockObject)
            {
                while (callbackQueue.Count > 0)
                {
                    Action action = callbackQueue.Dequeue();
                    action();
                }
            }
        }



        public static void Clear()
        {
            MsgList.Clear();
            callbackQueue.Clear();
        }
    }

}

